﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YJKArchUtils.Utils;
using YJKRevitBase.TopologySuite;
using YJKRevitKernel.RevitTopologySuite;
using YJKRevitDimensionText.OneKeyPlanDim.LevelDim;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.DimData
{
	public class DbCanopy : DbDimBase
	{
		public XYZ CenterPoint
		{
			get
			{
				return this.m_ptLocation;
			}
		}

		public DbCanopy(Element element)
		{
			this.m_Element = element;
			this.m_lstWall = KeyComponent.GetInstance().m_lstWall;
		}

		public override bool CreateSizeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSizeDim(doc))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			this.CreateDimLengthAndWidthAndGrid(this.m_canopyLength, this.m_liCanopyWidth, this.m_gridCanopyWidth);
			this.CreateDimLengthAndWidthAndGrid(this.m_canopyWidth, this.m_liCanopyLength, this.m_gridCanopyLength);
			return true;
		}

		private void CreateDimLengthAndWidthAndGrid(Line dimLine, Line dimGridLine, Grid grid)
		{
			if (null == dimLine)
			{
				return;
			}
			XYZ direction = dimLine.Direction;
			XYZ xyzpoint = dimLine.Project(this.m_ptLocation).XYZPoint;
			XYZ xyz = direction.CrossProduct((xyzpoint - this.m_ptLocation).Normalize());
			XYZ xyz2 = Geometry.RotateTo(direction, Math.PI*.5, xyz);
			Transform transform = Transform.CreateTranslation(xyz2 * AssistFunc.mmToFeet(600.0) * (double)(this.m_doc.ActiveView.Scale / 100));
			Line line = dimLine.CreateTransformed(transform) as Line;
			XYZ endPoint = line.GetEndPoint(0);
			XYZ endPoint2 = line.GetEndPoint(1);
			DetailCurve detailCurveWithPoint = CommonInterface.GetDetailCurveWithPoint(this.m_doc, endPoint, xyz2);
			DetailCurve detailCurveWithPoint2 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, endPoint2, xyz2);
			ReferenceArray referenceArray = new ReferenceArray();
			if (detailCurveWithPoint != null)
			{
				Reference reference = new Reference(detailCurveWithPoint);
				referenceArray.Append(reference);
			}
			if (detailCurveWithPoint2 != null)
			{
				Reference reference = new Reference(detailCurveWithPoint2);
				referenceArray.Append(reference);
			}
			if (grid != null)
			{
				XYZ xyz3 = (grid.Curve as Line).Project(endPoint).XYZPoint;
				xyz3 = new XYZ(xyz3.X, xyz3.Y, endPoint.Z);
				DetailCurve detailCurveWithPoint3 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz3, xyz2);
				if (detailCurveWithPoint3 != null)
				{
					Reference reference = new Reference(detailCurveWithPoint3);
					referenceArray.Append(reference);
				}
			}
			Dimension dimension = new SizeDimData(this.m_doc, line, referenceArray).CreateDim(true);
			if (dimension != null)
			{
				this.SetDimPosition(dimension, line, xyz2);
			}
		}

		private void SetDimPosition(Dimension newDim, Line lineRef, XYZ dir)
		{
			List<CurveLoop> componentAndSizeAndSlopeOcclusionArea = OcclusionArea.GetInstance().GetComponentAndSizeAndSlopeOcclusionArea();
			List<CurveLoop> sizeDimCurveLoop = OcclusionArea.GetSizeDimCurveLoop(newDim);
			List<CurveLoop> list = new List<CurveLoop>();
			XYZ origin = lineRef.Origin;
			XYZ ptEnd = origin;
			for (int i = 0; i < 3; i++)
			{
				ptEnd = CommonInterface.GetNextPositionByOffset(i, Common.MMToFeet(300.0), origin, dir);
				list = CommonInterface.MoveLstCurve(sizeDimCurveLoop, origin, ptEnd);
				bool flag = false;
				using (List<CurveLoop>.Enumerator enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (CommonInterface.IsExistOcclusion(enumerator.Current, componentAndSizeAndSlopeOcclusionArea))
						{
							flag = true;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				if (2 == i)
				{
					ptEnd = origin;
					break;
				}
			}
			OcclusionArea.GetInstance().m_lstSizeDimCvLoop.AddRange(list);
			CommonInterface.MoveElement(newDim, origin, ptEnd, this.m_doc);
		}

		private Dimension CreateDim(Line offsetLine, DetailCurve dc1, DetailCurve dc2, DetailCurve dc3)
		{
			ReferenceArray referenceArray = new ReferenceArray();
			Reference reference = new Reference(dc1);
			referenceArray.Append(reference);
			reference = new Reference(dc2);
			referenceArray.Append(reference);
			if (dc3 != null)
			{
				reference = new Reference(dc3);
				referenceArray.Append(reference);
			}
			return new SizeDimData(this.m_doc, offsetLine, referenceArray).CreateDim(true);
		}

		public override bool CreateLevelDim(Autodesk.Revit.DB.Document doc, out List<SingleLevelDimDataInfo> lstAnnotationSymbol)
		{
			if (!base.CreateLevelDim(doc, out lstAnnotationSymbol))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			if (null == this.m_liCanopyLengthWithZ)
			{
				return false;
			}
			XYZ xyz = (this.m_liCanopyLengthWithZ.GetEndPoint(0) + this.m_liCanopyLengthWithZ.GetEndPoint(1)) / 2.0;
			XYZ xyz2 = new XYZ(xyz.X, xyz.Y, 0.0);
			double thicknessWithWallType;
			Parameter parameter;
			if (this.m_Element is Floor)
			{
				Floor floor = this.m_Element as Floor;
				thicknessWithWallType = this.GetThicknessWithWallType(floor.FloorType);
				parameter = RevitElementExtension.GetParameter(floor, BuiltInParameter.FLOOR_ATTR_THICKNESS_PARAM);
			}
			else
			{
				FootPrintRoof footPrintRoof = this.m_Element as FootPrintRoof;
				thicknessWithWallType = this.GetThicknessWithWallType(footPrintRoof.RoofType);
				parameter = RevitElementExtension.GetParameter(footPrintRoof, BuiltInParameter.ROOF_ATTR_THICKNESS_PARAM);
			}
			if (parameter == null)
			{
				return false;
			}
			double num = xyz.Z + parameter.AsDouble() - thicknessWithWallType;
			AnnotationSymbol annotationSymbol = this.CreateLevelDim(xyz2, num);
			if (annotationSymbol != null)
			{
				SingleLevelDimDataInfo singleLevelDimDataInfo = new SingleLevelDimDataInfo(annotationSymbol);
				if (base.ComponentInSlopePlanarFace != null)
				{
					singleLevelDimDataInfo.LevelVal = num;
				}
				else
				{
					singleLevelDimDataInfo.LevelVal = base.dFloorLevelVal;
				}
				singleLevelDimDataInfo.PtLocation = xyz2;
				singleLevelDimDataInfo.bStepDownDim = false;
				singleLevelDimDataInfo.m_LstElementId.Add(this.m_Element.Id);
				lstAnnotationSymbol.Add(singleLevelDimDataInfo);
			}
			return true;
		}

		private AnnotationSymbol CreateLevelDim(XYZ ptLocationDim, double dFloorCoreLevel)
		{
			FamilyInstance familyInstance = new LevelDimData(this.m_doc)
			{
				DimVal = (AssistFunc.feetToMM(dFloorCoreLevel) / 1000.0).ToString("f3"),
				PtDimLocation = ptLocationDim
			}.CreateLevelDim();
			AnnotationSymbol result = null;
			if (familyInstance != null)
			{
				result = (familyInstance as AnnotationSymbol);
			}
			return result;
		}

		private double GetThicknessWithWallType(HostObjAttributes type)
		{
			double num = 0.0;
			CompoundStructure compoundStructure = type.GetCompoundStructure();
			int firstCoreLayerIndex = compoundStructure.GetFirstCoreLayerIndex();
			IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
			int count = layers.Count;
			new List<int>();
			for (int i = 0; i < count; i++)
			{
				CompoundStructureLayer compoundStructureLayer = layers[i];
				if (i < firstCoreLayerIndex)
				{
					num += compoundStructureLayer.Width;
				}
			}
			return num;
		}

		public override bool CreateSlopeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSlopeDim(doc))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			XYZ xyz = (this.m_liCanopyLengthWithZ.GetEndPoint(0) + this.m_liCanopyLengthWithZ.GetEndPoint(1)) / 2.0;
			XYZ ptStart = new XYZ(xyz.X, xyz.Y, 0.0);
			Curve curve = this.m_liCanopyLengthWithZ.Clone();
			curve.MakeUnbound();
			XYZ xyzpoint = curve.Project(this.m_ptLocation).XYZPoint;
			XYZ slopeDimDir = (this.m_ptLocation - xyzpoint).Normalize();
			new SlopeDimData(this.m_doc)
			{
				DimVal = this.CalSlopeValue(),
				PtStart = ptStart,
				SlopeDimDir = slopeDimDir
			}.CreateSlopeDim();
			return true;
		}

		private string CalSlopeValue()
		{
			string str = string.Empty;
			double num = this.m_face.FaceNormal.AngleTo(XYZ.BasisZ);
			if (Geometry.LessThan(Math.PI*.5, num))
			{
				num = Math.PI - num;
			}
			double num2 = 1.0 / Math.Tan(num);
			int num3 = (int)num2;
			if (Geometry.IsEqual(num2, (double)num3))
			{
				str = num3.ToString();
			}
			else
			{
				str = num2.ToString("f2");
			}
			return "1 : " + str;
		}

		public bool AnalysisInfo()
		{
			if (!base.IsNeedAnalysisInfo())
			{
				return true;
			}
			bool result;
			try
			{
				List<PlanarFace> allPlanarFace = GeometryHelper.GetAllPlanarFace(this.m_Element);
				PlanarFace planarFace = this.GetPlanarFace(allPlanarFace);
				if (null == planarFace)
				{
					result = false;
				}
				else
				{
					this.m_face = planarFace;
					RevitPolygonDataBean revitPolygonDataBean = null;
					List<CurveLoop> list = new List<CurveLoop>();
					list = planarFace.GetEdgesAsCurveLoops().ToList<CurveLoop>();
					if (list.Count < 1)
					{
						result = false;
					}
					else
					{
						List<Curve> newCurve = this.GetNewCurve(list);
						CurveArray curveArray = new CurveArray();
						foreach (Curve curve in newCurve)
						{
							curveArray.Append(curve);
						}
						this.m_ptLocation = YJKRevitTools.Centroid(curveArray);
						revitPolygonDataBean = new RevitPolygonDataBean(CurveLoop.Create(newCurve), null, 0);
						bool flag = false;
						foreach (Wall wall in this.m_lstWall)
						{
							Curve curve2 = (wall.Location as LocationCurve).Curve;
							if (!(curve2 is Arc))
							{
								XYZ xyz = Geometry.RotateTo((curve2 as Line).Direction, Math.PI*.5, XYZ.BasisZ);
								Transform transform = Transform.CreateTranslation(xyz * wall.Width / 2.0);
								Curve curve3 = curve2.CreateTransformed(transform);
								transform = Transform.CreateTranslation(-xyz * wall.Width / 2.0);
								Curve curve4 = curve2.CreateTransformed(transform);
								List<Curve> list2 = new List<Curve>
								{
									Line.CreateBound(curve3.GetEndPoint(0), curve3.GetEndPoint(1)),
									Line.CreateBound(curve3.GetEndPoint(1), curve4.GetEndPoint(1)),
									Line.CreateBound(curve4.GetEndPoint(1), curve4.GetEndPoint(0)),
									Line.CreateBound(curve4.GetEndPoint(0), curve3.GetEndPoint(0))
								};
								RevitPolygonDataBean revitPolygonDataBean2 = null;
								try
								{
									revitPolygonDataBean2 = new RevitPolygonDataBean(CurveLoop.Create(list2), null, 0);
								}
								catch
								{
									continue;
								}
								TopologyRelateKindEnum topologyRelateKindEnum = 0;
                                new RevitPolygonRelateOperater().TryGetPolygonRelate(revitPolygonDataBean, revitPolygonDataBean2, out topologyRelateKindEnum);
                                if ((int)topologyRelateKindEnum != 1)
								{
									flag = true;
									this.GetLengthWithZ(wall, list[0], newCurve);
									this.GetLengthAndWidthEdge(wall, newCurve);
									break;
								}
							}
						}
						result = flag;
					}
				}
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private void GetLengthWithZ(Wall wall, CurveLoop curveLoop, List<Curve> lstCv)
		{
			Curve curve = (wall.Location as LocationCurve).Curve;
			if (curve is Arc)
			{
				return;
			}
			Line line = curve as Line;
			Line line2 = null;
			double num = double.MaxValue;
			foreach (Curve curve2 in lstCv)
			{
				if (!(curve2 is Arc))
				{
					XYZ xyz = (curve2.GetEndPoint(0) + curve2.GetEndPoint(1)) / 2.0;
					double num2 = line.Distance(xyz);
					if (Geometry.LessThan(num2, num) && Geometry.IsParallel(line.Direction, (curve2 as Line).Direction, 1E-09))
					{
						num = num2;
						line2 = (curve2 as Line);
					}
				}
			}
			if (null == line2)
			{
				return;
			}
			XYZ endPoint = line2.GetEndPoint(0);
			XYZ endPoint2 = line2.GetEndPoint(1);
			foreach (Curve curve3 in curveLoop)
			{
				XYZ endPoint3 = curve3.GetEndPoint(0);
				XYZ endPoint4 = curve3.GetEndPoint(1);
				if (Geometry.IsEqual(endPoint.X, endPoint3.X) && Geometry.IsEqual(endPoint.Y, endPoint3.Y) && Geometry.IsEqual(endPoint2.X, endPoint4.X) && Geometry.IsEqual(endPoint2.Y, endPoint4.Y))
				{
					this.m_liCanopyLengthWithZ = (curve3 as Line);
					break;
				}
			}
		}

		private void GetLengthAndWidthEdge(Wall wall, List<Curve> lstCv)
		{
			Curve curve = (wall.Location as LocationCurve).Curve;
			if (curve is Arc)
			{
				return;
			}
			Line line = curve as Line;
			double maxValue = double.MaxValue;
			double maxValue2 = double.MaxValue;
			foreach (Curve cv in lstCv)
			{
				this.GetLengthAndWidthEdge(line, ref maxValue, ref maxValue2, cv);
			}
			if (lstCv.Count == 4)
			{
				foreach (Curve curve2 in lstCv)
				{
					if (Geometry.IsParallel(line.Direction, (curve2 as Line).Direction, 1E-09))
					{
						try
						{
							XYZ endPoint = this.m_liCanopyLengthWithZ.GetEndPoint(0);
							XYZ xyz = new XYZ(endPoint.X, endPoint.Y, 0.0);
							XYZ endPoint2 = this.m_liCanopyLengthWithZ.GetEndPoint(1);
							XYZ xyz2 = new XYZ(endPoint2.X, endPoint2.Y, 0.0);
							if (!curve2.GetEndPoint(0).IsAlmostEqualTo(xyz) || !curve2.GetEndPoint(1).IsAlmostEqualTo(xyz2))
							{
								this.m_canopyLength = (curve2 as Line);
							}
							continue;
						}
						catch (Exception)
						{
							this.m_canopyLength = (curve2 as Line);
							continue;
						}
					}
					if (Geometry.IsVertical(line.Direction, (curve2 as Line).Direction, 1E-09))
					{
						this.m_canopyWidth = (curve2 as Line);
					}
				}
			}
		}

		private void GetLengthAndWidthEdge(Line wallLine, ref double dMinVertical, ref double dMinParallel, Curve cv)
		{
			foreach (DbAxial dbAxial in KeyComponent.GetInstance().m_lstDbAxial)
			{
				double maxValue = double.MaxValue;
				XYZ fixedXyz = (cv.GetEndPoint(0) + cv.GetEndPoint(1)) / 2.0;
				if (dbAxial != null)
				{
					Grid gridNearestXZY = dbAxial.GetGridNearestXZY(fixedXyz, ref maxValue);
					if (gridNearestXZY != null && !(gridNearestXZY.Curve is Arc))
					{
						Line line = gridNearestXZY.Curve as Line;
						if (Geometry.IsParallel(wallLine.Direction, line.Direction, 1E-09) && Geometry.IsParallel(wallLine.Direction, (cv as Line).Direction, 1E-09))
						{
							if (Geometry.LessThan(maxValue, dMinParallel) && maxValue != 0.0)
							{
								dMinParallel = maxValue;
								this.m_gridCanopyLength = gridNearestXZY;
								this.m_liCanopyLength = (cv as Line);
							}
						}
						else if (Geometry.IsVertical(wallLine.Direction, line.Direction, 1E-09) && Geometry.IsVertical(wallLine.Direction, (cv as Line).Direction, 1E-09) && Geometry.LessThan(maxValue, dMinVertical) && maxValue != 0.0)
						{
							dMinVertical = maxValue;
							this.m_gridCanopyWidth = gridNearestXZY;
							this.m_liCanopyWidth = (cv as Line);
						}
					}
				}
			}
		}

		private List<Curve> GetNewCurve(List<CurveLoop> lstCl)
		{
			List<Curve> list = new List<Curve>();
			foreach (Curve curve in lstCl[0])
			{
				if (curve is Line)
				{
					XYZ endPoint = curve.GetEndPoint(0);
					XYZ xyz = new XYZ(endPoint.X, endPoint.Y, 0.0);
					XYZ endPoint2 = curve.GetEndPoint(1);
					XYZ xyz2 = new XYZ(endPoint2.X, endPoint2.Y, 0.0);
					list.Add(Line.CreateBound(xyz, xyz2));
				}
				else
				{
					Arc arc = curve as Arc;
					XYZ endPoint3 = arc.GetEndPoint(0);
					XYZ xyz3 = new XYZ(endPoint3.X, endPoint3.Y, 0.0);
					XYZ endPoint4 = arc.GetEndPoint(1);
					XYZ xyz4 = new XYZ(endPoint4.X, endPoint4.Y, 0.0);
					XYZ center = arc.Center;
					XYZ xyz5 = new XYZ(center.X, center.Y, 0.0);
					list.Add(Arc.Create(xyz3, xyz4, xyz5));
				}
			}
			return list;
		}

		private PlanarFace GetPlanarFace(List<PlanarFace> lstPlanarFace)
		{
			int num = 0;
			PlanarFace result = null;
			List<PlanarFace> list = new List<PlanarFace>();
			foreach (PlanarFace planarFace in lstPlanarFace)
			{
				if (Geometry.LessThan(planarFace.FaceNormal.Z, 0.0))
				{
					result = planarFace;
					list.Add(planarFace);
					num++;
				}
			}
			if (num == 1)
			{
				return result;
			}
			double num2 = double.MaxValue;
			foreach (PlanarFace planarFace2 in list)
			{
				double z = planarFace2.Origin.Z;
				if (Geometry.LessThan(z, num2))
				{
					num2 = z;
					result = planarFace2;
				}
			}
			return result;
		}

		private Element m_Element;

		private List<Wall> m_lstWall = new List<Wall>();

		private Line m_liCanopyLength;

		private Line m_liCanopyWidth;

		private Line m_canopyLength;

		private Line m_canopyWidth;

		private Grid m_gridCanopyLength;

		private Grid m_gridCanopyWidth;

		private Line m_liCanopyLengthWithZ;

		private XYZ m_ptLocation;

		private PlanarFace m_face;
	}
}
